/**
 * MIT License
 *
 * Copyright (c) 2024 小村程序员
 * Email: 397237738@qq.com
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.open.cobertura.report.html.provider;

import org.open.cobertura.data.ICoberturaClassCovered;
import org.open.cobertura.data.ICoberturaLineCovered;
import org.open.cobertura.data.ICoberturaMethodCovered;
import org.open.cobertura.data.ICoberturaPackageCovered;
import org.open.cobertura.model.*;
import org.open.cobertura.report.html.IReportCoverage;
import org.open.cobertura.util.DataUtil;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 覆盖率报告数据提供者
 */
public class ReportCoverageProvider implements IReportCoverage {

    @Override
    public ReportCoverage providePackageCoverage(List<ICoberturaPackageCovered> coberturaPackageCovereds) {
        ReportCoverage reportCoverage=new ReportCoverage();
        Map<String,List<ClassCoverage>> classCoverageMap=new LinkedHashMap<>();
        Map<String,List<MethodCoverage>> methodCoverageMap=new LinkedHashMap<>();
        Map<String,List<LineCoverage>> lineCoverageMap=new LinkedHashMap<>();
        List<PackageCoverage> packageCoverageList=new ArrayList<>();
        for(ICoberturaPackageCovered coberturaPackageCovered:coberturaPackageCovereds){
            List<ClassCoverage> classCoverageList=new ArrayList<>();
            PackageCoverage packageCoverage=new PackageCoverage();
            packageCoverage.setPackageName(coberturaPackageCovered.getPackageName());
            packageCoverage.setInstruCoveredCount(coberturaPackageCovered.getInstructionCounter().getCoveredCount());
            packageCoverage.setInstruMissedCount(coberturaPackageCovered.getInstructionCounter().getMissedCount());
            packageCoverage.setInstruTotalCount(coberturaPackageCovered.getInstructionCounter().getTotalCount());
            packageCoverage.setInstruCoveredRatio(DataUtil.calculateCoverageRatio(coberturaPackageCovered.getInstructionCounter().getCoveredCount(),coberturaPackageCovered.getInstructionCounter().getTotalCount()));
            packageCoverage.setBranchesCoveredCount(coberturaPackageCovered.getBranchCounter().getCoveredCount());
            packageCoverage.setBranchesMissedCount(coberturaPackageCovered.getBranchCounter().getMissedCount());
            packageCoverage.setBranchesTotalCount(coberturaPackageCovered.getBranchCounter().getTotalCount());
            packageCoverage.setBranchesCoveredRatio(DataUtil.calculateCoverageRatio(coberturaPackageCovered.getBranchCounter().getCoveredCount(),coberturaPackageCovered.getBranchCounter().getTotalCount()));
            packageCoverage.setClassCoveredCount(coberturaPackageCovered.getClassCounter().getCoveredCount());
            packageCoverage.setClassMissedCount(coberturaPackageCovered.getClassCounter().getMissedCount());
            packageCoverage.setClassTotalCount(coberturaPackageCovered.getClassCounter().getTotalCount());
            packageCoverage.setClassCoveredRatio(DataUtil.calculateCoverageRatio(coberturaPackageCovered.getClassCounter().getCoveredCount(),coberturaPackageCovered.getPackageCounter().getTotalCount()));
            packageCoverage.setLineCoveredCount(coberturaPackageCovered.getLineCounter().getCoveredCount());
            packageCoverage.setLineMissedCount(coberturaPackageCovered.getLineCounter().getMissedCount());
            packageCoverage.setLineTotalCount(coberturaPackageCovered.getLineCounter().getTotalCount());
            packageCoverage.setLineCoveredRatio(DataUtil.calculateCoverageRatio(coberturaPackageCovered.getLineCounter().getCoveredCount(),coberturaPackageCovered.getLineCounter().getTotalCount()));
            packageCoverage.setCxtyCoveredCount(coberturaPackageCovered.getComplexityCounter()==null?0:coberturaPackageCovered.getComplexityCounter().getCoveredCount());
            packageCoverage.setCxtyMissedCount(coberturaPackageCovered.getComplexityCounter()==null?0:coberturaPackageCovered.getComplexityCounter().getMissedCount());
            packageCoverage.setCxtyTotalCount(coberturaPackageCovered.getComplexityCounter()==null?0:coberturaPackageCovered.getComplexityCounter().getTotalCount());
            packageCoverage.setCxtyCoveredRatio(coberturaPackageCovered.getComplexityCounter()==null?0:DataUtil.calculateCoverageRatio(coberturaPackageCovered.getComplexityCounter().getCoveredCount(),coberturaPackageCovered.getComplexityCounter().getTotalCount()));
            packageCoverage.setMethodMissedCount(coberturaPackageCovered.getMethodCounter().getMissedCount());
            packageCoverage.setMethodCoveredCount(coberturaPackageCovered.getMethodCounter().getCoveredCount());
            packageCoverage.setMethodTotalCount(coberturaPackageCovered.getMethodCounter().getTotalCount());
            packageCoverage.setMethodCoveredRatio(DataUtil.calculateCoverageRatio(coberturaPackageCovered.getMethodCounter().getCoveredCount(),coberturaPackageCovered.getMethodCounter().getTotalCount()));
            packageCoverageList.add(packageCoverage);
            List<ICoberturaClassCovered> classCoveredList=coberturaPackageCovered.getCoberturaClassCovered();
            for(ICoberturaClassCovered coberturaClassCovered:classCoveredList){
                List<LineCoverage> lineCoverageList=new ArrayList<>();
                List<MethodCoverage> methodCoverageList=new ArrayList<>();
                ClassCoverage classCoverage=new ClassCoverage();
                classCoverage.setPackageName(coberturaPackageCovered.getPackageName());
                String sourceName=coberturaClassCovered.getClassName();
                if(sourceName.indexOf("{...}")!=-1){
                    sourceName=sourceName.substring(0,sourceName.replaceAll("\\{...}","").lastIndexOf("."));
                }
                classCoverage.setSourceName(sourceName);
                classCoverage.setClassName(coberturaClassCovered.getClassName());
                classCoverage.setInstruCoveredCount(coberturaClassCovered.getInstructionCounter().getCoveredCount());
                classCoverage.setInstruMissedCount(coberturaClassCovered.getInstructionCounter().getMissedCount());
                classCoverage.setInstruTotalCount(coberturaClassCovered.getInstructionCounter().getTotalCount());
                classCoverage.setInstruCoveredRatio(DataUtil.calculateCoverageRatio(coberturaClassCovered.getInstructionCounter().getCoveredCount(),coberturaClassCovered.getInstructionCounter().getTotalCount()));
                classCoverage.setBranchesCoveredCount(coberturaClassCovered.getBranchCounter().getCoveredCount());
                classCoverage.setBranchesMissedCount(coberturaClassCovered.getBranchCounter().getMissedCount());
                classCoverage.setBranchesTotalCount(coberturaClassCovered.getBranchCounter().getTotalCount());
                classCoverage.setBranchesCoveredRatio(DataUtil.calculateCoverageRatio(coberturaClassCovered.getBranchCounter().getCoveredCount(),coberturaClassCovered.getBranchCounter().getTotalCount()));
                classCoverage.setClassCoveredCount(coberturaClassCovered.getClassCounter().getCoveredCount());
                classCoverage.setClassMissedCount(coberturaClassCovered.getClassCounter().getMissedCount());
                classCoverage.setClassTotalCount(coberturaClassCovered.getClassCounter().getTotalCount());
                classCoverage.setClassCoveredRatio(DataUtil.calculateCoverageRatio(coberturaClassCovered.getClassCounter().getCoveredCount(),coberturaClassCovered.getClassCounter().getTotalCount()));
                classCoverage.setLineCoveredCount(coberturaClassCovered.getLineCounter().getCoveredCount());
                classCoverage.setLineMissedCount(coberturaClassCovered.getLineCounter().getMissedCount());
                classCoverage.setLineTotalCount(coberturaClassCovered.getLineCounter().getTotalCount());
                classCoverage.setLineCoveredRatio(DataUtil.calculateCoverageRatio(coberturaClassCovered.getLineCounter().getCoveredCount(),coberturaClassCovered.getLineCounter().getTotalCount()));
                classCoverage.setCxtyCoveredCount(coberturaClassCovered.getComplexityCounter()==null?0:coberturaClassCovered.getComplexityCounter().getCoveredCount());
                classCoverage.setCxtyMissedCount(coberturaClassCovered.getComplexityCounter()==null?0:coberturaClassCovered.getComplexityCounter().getMissedCount());
                classCoverage.setCxtyTotalCount(coberturaClassCovered.getComplexityCounter()==null?0:coberturaClassCovered.getComplexityCounter().getTotalCount());
                classCoverage.setCxtyCoveredRatio(coberturaClassCovered.getComplexityCounter()==null?0:DataUtil.calculateCoverageRatio(coberturaClassCovered.getComplexityCounter().getCoveredCount(),coberturaClassCovered.getComplexityCounter().getTotalCount()));
                classCoverage.setMethodMissedCount(coberturaClassCovered.getMethodCounter().getMissedCount());
                classCoverage.setMethodCoveredCount(coberturaClassCovered.getMethodCounter().getCoveredCount());
                classCoverage.setMethodTotalCount(coberturaClassCovered.getMethodCounter().getTotalCount());
                classCoverage.setMethodCoveredRatio(DataUtil.calculateCoverageRatio(coberturaClassCovered.getMethodCounter().getCoveredCount(),coberturaClassCovered.getMethodCounter().getTotalCount()));
                classCoverageList.add(classCoverage);
                classCoverageMap.put(coberturaPackageCovered.getPackageName(),classCoverageList);
                List<ICoberturaMethodCovered>  coberturaMethodCovereds=coberturaClassCovered.getCoberturaMethodCovered();
                for(ICoberturaMethodCovered coberturaMethodCovered:coberturaMethodCovereds){

                    lineCoverageMap.put(coberturaPackageCovered.getPackageName()+"."+classCoverage.getClassName(),lineCoverageList);
                    MethodCoverage methodCoverage=new MethodCoverage();
                    methodCoverage.setPackageName(coberturaPackageCovered.getPackageName());
                    methodCoverage.setClassName(coberturaClassCovered.getClassName());
                    methodCoverage.setName(coberturaMethodCovered.getMethodName());
                    methodCoverage.setInstruCoveredCount(coberturaMethodCovered.getInstructionCounter().getCoveredCount());
                    methodCoverage.setInstruMissedCount(coberturaMethodCovered.getInstructionCounter().getMissedCount());
                    methodCoverage.setInstruTotalCount(coberturaMethodCovered.getInstructionCounter().getTotalCount());
                    methodCoverage.setInstruCoveredRatio(DataUtil.calculateCoverageRatio(coberturaMethodCovered.getInstructionCounter().getMissedCount(),coberturaMethodCovered.getInstructionCounter().getCoveredCount()));
                    methodCoverage.setBranchesCoveredCount(coberturaMethodCovered.getBranchCounter().getCoveredCount());
                    methodCoverage.setBranchesMissedCount(coberturaMethodCovered.getBranchCounter().getMissedCount());
                    methodCoverage.setBranchesTotalCount(coberturaMethodCovered.getBranchCounter().getTotalCount());
                    methodCoverage.setBranchesCoveredRatio(DataUtil.calculateCoverageRatio(coberturaMethodCovered.getBranchCounter().getCoveredCount(),coberturaMethodCovered.getBranchCounter().getTotalCount()));
                    methodCoverage.setLineCoveredCount(coberturaMethodCovered.getLineCounter().getCoveredCount());
                    methodCoverage.setLineMissedCount(coberturaMethodCovered.getLineCounter().getMissedCount());
                    methodCoverage.setLineTotalCount(coberturaMethodCovered.getLineCounter().getTotalCount());
                    methodCoverage.setLineCoveredRatio(DataUtil.calculateCoverageRatio(coberturaMethodCovered.getLineCounter().getCoveredCount(),coberturaMethodCovered.getLineCounter().getTotalCount()));
                    methodCoverage.setCxtyCoveredCount(coberturaMethodCovered.getComplexityCounter()==null?0:coberturaMethodCovered.getComplexityCounter().getCoveredCount());
                    methodCoverage.setCxtyMissedCount(coberturaMethodCovered.getComplexityCounter()==null?0:coberturaMethodCovered.getComplexityCounter().getMissedCount());
                    methodCoverage.setCxtyTotalCount(coberturaMethodCovered.getComplexityCounter()==null?0:coberturaMethodCovered.getComplexityCounter().getTotalCount());
                    methodCoverage.setCxtyCoveredRatio(coberturaMethodCovered.getComplexityCounter()==null?0:DataUtil.calculateCoverageRatio(coberturaMethodCovered.getComplexityCounter().getCoveredCount(),coberturaMethodCovered.getComplexityCounter().getTotalCount()));
                    methodCoverage.setMethodMissedCount(coberturaMethodCovered.getMethodCounter().getMissedCount());
                    methodCoverage.setMethodCoveredCount(coberturaMethodCovered.getMethodCounter().getCoveredCount());
                    methodCoverage.setMethodTotalCount(coberturaMethodCovered.getMethodCounter().getTotalCount());
                    methodCoverage.setMethodCoveredRatio(DataUtil.calculateCoverageRatio(coberturaMethodCovered.getMethodCounter().getCoveredCount(),coberturaMethodCovered.getMethodCounter().getTotalCount()));
                    methodCoverageList.add(methodCoverage);
                    methodCoverageMap.put(coberturaPackageCovered.getPackageName()+"."+coberturaClassCovered.getClassName(),methodCoverageList);
                }

                for(ICoberturaLineCovered coberturaLineCovered:coberturaClassCovered.getCoberturaLineCovered()){

                    LineCoverage lineCoverage=new LineCoverage();
                    lineCoverage.setPackageName(coberturaPackageCovered.getPackageName());
                    lineCoverage.setClassName(coberturaClassCovered.getClassName());
                    lineCoverage.setInstruCoveredCount(coberturaLineCovered.getInstructionCounter().getCoveredCount());
                    lineCoverage.setInstruMissedCount(coberturaLineCovered.getInstructionCounter().getMissedCount());
                    lineCoverage.setInstruTotalCount(coberturaLineCovered.getInstructionCounter().getTotalCount());
                    lineCoverage.setInstruCoveredRatio(DataUtil.calculateCoverageRatio(coberturaLineCovered.getInstructionCounter().getMissedCount(),coberturaLineCovered.getInstructionCounter().getCoveredCount()));
                    lineCoverage.setBranchesCoveredCount(coberturaLineCovered.getBranchCounter().getCoveredCount());
                    lineCoverage.setBranchesMissedCount(coberturaLineCovered.getBranchCounter().getMissedCount());
                    lineCoverage.setBranchesTotalCount(coberturaLineCovered.getBranchCounter().getTotalCount());
                    lineCoverage.setBranchesCoveredRatio(DataUtil.calculateCoverageRatio(coberturaLineCovered.getBranchCounter().getCoveredCount(),coberturaLineCovered.getBranchCounter().getTotalCount()));
                    lineCoverage.setLine(coberturaLineCovered.getLineNumber());
                    lineCoverage.setOffset(coberturaLineCovered.getOffset());
                    lineCoverageList.add(lineCoverage);
                }
            }
        }

        reportCoverage.setPackageCoverageList(packageCoverageList);
        reportCoverage.setClassCoverageMap(classCoverageMap);
        reportCoverage.setMethodCoverageMap(methodCoverageMap);
        reportCoverage.setLineCoverageMap(lineCoverageMap);
        return reportCoverage;
    }
}
